// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#pragma once

#include <turbo/base/macros.h>

namespace nebula {

    /// EXPERIMENTAL: Layout specification for a data type
    struct TURBO_EXPORT DataTypeLayout {
            enum BufferKind {
                FIXED_WIDTH, VARIABLE_WIDTH, BITMAP, ALWAYS_NULL
            };

            /// Layout specification for a single data type buffer
            struct BufferSpec {
                BufferKind kind;
                int64_t byte_width;  // For FIXED_WIDTH

                bool operator==(const BufferSpec &other) const {
                    return kind == other.kind &&
                           (kind != FIXED_WIDTH || byte_width == other.byte_width);
                }

                bool operator!=(const BufferSpec &other) const { return !(*this == other); }
            };

            static BufferSpec FixedWidth(int64_t w) { return BufferSpec{FIXED_WIDTH, w}; }

            static BufferSpec VariableWidth() { return BufferSpec{VARIABLE_WIDTH, -1}; }

            static BufferSpec Bitmap() { return BufferSpec{BITMAP, -1}; }

            static BufferSpec AlwaysNull() { return BufferSpec{ALWAYS_NULL, -1}; }

            /// A vector of buffer layout specifications, one for each expected buffer
            std::vector<BufferSpec> buffers;
            /// Whether this type expects an associated dictionary array.
            bool has_dictionary = false;
            /// If this is provided, the number of buffers expected is only lower-bounded by
            /// buffers.size(). Buffers beyond this lower bound are expected to conform to
            /// variadic_spec.
            std::optional<BufferSpec> variadic_spec;

            explicit DataTypeLayout(std::vector<BufferSpec> buffers,
            std::optional<BufferSpec> variadic_spec = {})
            : buffers(std::move(buffers)), variadic_spec(variadic_spec) {}
    };

}  // namespace nebula
